package _1_常用数据类型_关键字;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import org.junit.Test;

/**
 * 浮点数
 */
public class _2_FloatingPoint {

  @Test
  public void infinity() {
    // POSITIVE_INFINITY  Double.NEGATIVE_INFINITY  Double.NaN
    // 看源码上的文档
    System.out.println(Double.POSITIVE_INFINITY);
    System.out.println(Double.NEGATIVE_INFINITY);

    System.out.println(2.0 - 1.1);
    // There is no precise binary representation of the fraction 1/10, just as there is
    // no accurate representation of the fraction 1/3 in the decimal system. If you need
    // precise numerical computations without round off errors, use the BigDecimal class.
  }

  @Test
  /**
   * @see BigDecimal#BigDecimal(double)
   */
  public void bigDecimal() {
    // 从double和float通过构造器创建的BigDecimal，也会造成精度丢失

    BigDecimal a = new BigDecimal(1.1);
    BigDecimal b = new BigDecimal(1.2);
    System.out.println(a.add(b));

    // 应该使用 valueOf() 方法，或者自己转为string
    double d = 1.024;
    BigDecimal bigDecimal = BigDecimal.valueOf(d);
    BigDecimal bigDecimal1 = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP);
    System.out.println(bigDecimal1);

    BigDecimal bigDecimal2 = new BigDecimal(Double.toString(d));
    BigDecimal bigDecimal3 = bigDecimal2.setScale(2, BigDecimal.ROUND_HALF_UP);
    System.out.println(bigDecimal3);

    BigDecimal bigDecimal4 = BigDecimal.valueOf(0.12567);
    System.out.println(String.valueOf(bigDecimal4));
  }


  /**
   * 四舍五入 返回 double/float
   */
  @Test
  public void roundHalfUp() {
    // 使用 Math.round() 间接获取
    double d = 114.145;
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
      double d2 = (double) Math.round(d * 100) / 100;
    }
    long end1 = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
      BigDecimal b = new BigDecimal(String.valueOf(d));
      double d3 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    long end2 = System.currentTimeMillis();
    System.out.println("使用Math.round: " + (end1 - start));
    System.out.println("使用BigDecimal: " + (end2 - end1));
    float f = (float) Math.round(d * 100) / 100;
    System.out.println(d);
    System.out.println(f);

    // 使用 BigDecimal.ROUND_HALF_UP 四舍五入
    // BigDecimal.ROUND_HALF_DOWN 是五舍六入
  }

  @Test
  public void intChuFa() {
    System.out.println(1 / 2);
    System.out.println(1 / 2f);
    System.out.println(1 / 2.0);
    System.out.println(1.0 / 2);
  }
  /**
   * 四舍五入 返回 String
   */
  @Test
  public void roundHalfUpString() {
    double d = 114.145;
    // #.00表示保留后两位，它的处理方式是直接截掉不要的尾数，不四舍五入
    DecimalFormat df = new DecimalFormat("#.00");
    String str = df.format(d);
    System.out.println(str);
    // %.2f表示保留后两位，能四舍五入
    System.out.println(String.format("%.2f", d));

    NumberFormat nf = NumberFormat.getNumberInstance();
    nf.setMaximumFractionDigits(2);

    // 如果不需要四舍五入，可以使用RoundingMode.DOWN
    nf.setRoundingMode(RoundingMode.UP);
    System.out.println(nf.format(d));
  }

}
